#include "stdafx.h"
#include "DateTime.h"
#include "Log.h"
#include "System.h"

namespace Core
{
	std::ostream& operator<<(std::ostream& p_Out, LogLevels p_LogLevel)
	{
		switch(p_LogLevel)
		{
		case LogLevel_Normal:
			p_Out << " Normal ";
			break;
		case LogLevel_Info:
			p_Out << "  Info  ";
			break;
		case LogLevel_Warning:
			p_Out << "Warning ";
			break;
		case LogLevel_Error:
			p_Out << " Error  ";
			break;
		case LogLevel_Critical:
			p_Out << "Critical";
			break;
		}
		return p_Out;
	}

	Log::Log()
	{
		m_WriteToCout = true;
		m_WriteToLogFile = false;
	}

	void Log::WriteToCOut(LogLevels p_LogLevel, std::string p_String)
	{
#ifdef WIN32
		switch(p_LogLevel)
		{
		case LogLevel_Normal:
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
			break;
		case LogLevel_Info:
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN | FOREGROUND_INTENSITY);
			break;
		case LogLevel_Warning:
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_BLUE | FOREGROUND_INTENSITY);
			break;
		case LogLevel_Error:
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
			break;
		case LogLevel_Critical:
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_INTENSITY);
			break;
		}
		std::cout << p_String << std::endl;
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
#else
		switch(p_LogLevel)
		{
		case LogLevel_Normal:
			printf("\033[22;37m");
			break;
		case LogLevel_Info:
			printf("\033[01;32m");
			break;
		case LogLevel_Warning:
			printf("\033[01;34m");
			break;
		case LogLevel_Error:
			printf("\033[01;35m");
			break;
		case LogLevel_Critical:
			printf("\033[01;31m");
			break;
		}
		std::cout << p_String << std::endl;
		printf("\033[22;37m");
#endif
	}

	void Log::WriteToLogFile(LogLevels p_LogLevel, std::string p_String)
	{
		std::ofstream& t_OFStream = m_LogFile.GetStream();
		t_OFStream << p_String << std::endl;
		t_OFStream.flush();
	}

	void Log::Write(LogLevels p_LogLevel, std::string p_String)
	{
		m_Mutex.Lock();
		DateTime t_DateTime;
		std::string t_String = t_DateTime.ToString("[%y-%m-%d %H:%M:%S] ") + p_String;
		if(m_WriteToCout) WriteToCOut(p_LogLevel, t_String);
		if(m_WriteToLogFile) WriteToLogFile(p_LogLevel, t_String);
		m_Mutex.Unlock();
	}

	LogFileWriter& Log::GetLogFile()
	{
		return m_LogFile;
	}

	void Log::SetWriteToCOut(bool p_WriteToCOut)
	{
		m_WriteToCout = p_WriteToCOut;
	}

	void Log::SetWriteToLogFile(bool p_WriteToLogFile)
	{
		m_WriteToLogFile = p_WriteToLogFile;
	}
}
